#pragma once
#include "afxcmn.h"


typedef float RotationMouseSensitivity;
typedef float TranslationMouseSensitivity;
typedef float ScaleMouseSensitivity;
typedef int   SensitivitySliderPosition;

// CMouseSettingsDialog dialog

class CMouseSettingsDialog : public CDialogEx
{
	DECLARE_DYNAMIC(CMouseSettingsDialog)

public:
	CMouseSettingsDialog(CWnd* pParent = NULL);         // standard constructor
	virtual ~CMouseSettingsDialog();

    // Dialog Data
	enum { IDD = IDD_MOUSE_SETTINGS_DLG };

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

	DECLARE_MESSAGE_MAP()
private:
    CSliderCtrl m_RotSensitivityControl;
    CSliderCtrl m_TraSensitivityControl;
    CSliderCtrl m_ScaSensitivityControl;

    const int m_nTickFrequency;

    const int m_nSensitivitySliderRangeMin;
    const int m_nSensitivitySliderRangeMax;

    const float m_fSensitivityRangeMin;
    const float m_fSensitivityRangeMax;

    float m_fRotSensitivityFactor;
    float m_fTraSensitivityFactor;
    float m_fScaSensitivityFactor;

    int m_nRotSensitivitySliderPos;
    int m_nTraSensitivitySliderPos;
    int m_nScaSensitivitySliderPos;

    int sensitivityToPosition(float value, float sensFactor) const;
    float positionToSensitivity(int value, float sensFactor) const;

    void restoreDefaults();

public:
    virtual BOOL OnInitDialog();

    void setMouseSliderPos(int  rotSens, int  traSens, int  scaSens);
    void getMouseSliderPos(int& rotSens, int& traSens, int& scaSens) const;

    void setMouseSensitivityFactors(float  rotF, float  traF, float  scaF);
    void getMouseSensitivityFactors(float& rotF, float& traF, float& scaF) const;

    void setMouseSensitivity(float  rotSens, float  traSens, float  scaSens);
    void getMouseSensitivity(float& rotSens, float& traSens, float& scaSens) const;

    afx_msg void OnBnClickedOk();
    afx_msg void OnBnClickedRestoreDefaults();
};



inline void CMouseSettingsDialog::setMouseSensitivityFactors(float rotF,
                                                             float traF,
                                                             float scaF)
{
    m_fRotSensitivityFactor = rotF;
    m_fTraSensitivityFactor = traF;
    m_fScaSensitivityFactor = scaF;
}


inline void CMouseSettingsDialog::getMouseSensitivityFactors(float& rotF,
                                                             float& traF,
                                                             float& scaF) const
{
    rotF = m_fRotSensitivityFactor;
    traF = m_fTraSensitivityFactor;
    scaF = m_fScaSensitivityFactor;
}


inline void CMouseSettingsDialog::getMouseSliderPos(int& rotSensitivity,
                                                    int& traSensitivity,
                                                    int& scaSensitivity) const
{
    rotSensitivity = m_nRotSensitivitySliderPos;
    traSensitivity = m_nTraSensitivitySliderPos;
    scaSensitivity = m_nScaSensitivitySliderPos;
}


inline void CMouseSettingsDialog::setMouseSliderPos(int rotSensitivity,
                                                    int traSensitivity,
                                                    int scaSensitivity)
{
    m_nRotSensitivitySliderPos = rotSensitivity;
    m_nTraSensitivitySliderPos = traSensitivity;
    m_nScaSensitivitySliderPos = scaSensitivity;
}


inline void CMouseSettingsDialog::getMouseSensitivity(float& rotSensitivity,
                                                      float& traSensitivity,
                                                      float& scaSensitivity) const
{
    rotSensitivity = positionToSensitivity( m_nRotSensitivitySliderPos, 
        m_fRotSensitivityFactor );
    traSensitivity = positionToSensitivity( m_nTraSensitivitySliderPos,
        m_fTraSensitivityFactor );
    scaSensitivity = positionToSensitivity( m_nScaSensitivitySliderPos,
        m_fScaSensitivityFactor );
}


inline void CMouseSettingsDialog::setMouseSensitivity(float rotSensitivity,
                                                      float traSensitivity,
                                                      float scaSensitivity)
{
    m_nRotSensitivitySliderPos =
        sensitivityToPosition( rotSensitivity, m_fRotSensitivityFactor );
    m_nTraSensitivitySliderPos =
        sensitivityToPosition( traSensitivity, m_fTraSensitivityFactor );
    m_nScaSensitivitySliderPos =
        sensitivityToPosition( scaSensitivity, m_fScaSensitivityFactor );
}



// Private methods /////////////////////////////////////////////////////////////

inline int CMouseSettingsDialog::sensitivityToPosition(float value,
                                                       float sensFactor) const
{
    value /= sensFactor;

    // stay in range
    value = max(m_fSensitivityRangeMin, value);
    value = min(m_fSensitivityRangeMax, value);

    // 0.5f is for rounding instead of flooring
    int result = static_cast<int>( 0.5f + (value - m_fSensitivityRangeMin) /
        (m_fSensitivityRangeMax - m_fSensitivityRangeMin) *
        (m_nSensitivitySliderRangeMax - m_nSensitivitySliderRangeMin) ) +
        m_nSensitivitySliderRangeMin;

    // return in range
    result = max(m_nSensitivitySliderRangeMin, result);
    result = min(m_nSensitivitySliderRangeMax, result);

    return result;
}


inline float CMouseSettingsDialog::positionToSensitivity(int value,
                                                         float sensFactor) const
{
    // get in range
    value = max(m_nSensitivitySliderRangeMin, value);
    value = min(m_nSensitivitySliderRangeMax, value);

    float result = static_cast<float>(value - m_nSensitivitySliderRangeMin) *
           (m_fSensitivityRangeMax - m_fSensitivityRangeMin) /
           (m_nSensitivitySliderRangeMax - m_nSensitivitySliderRangeMin) +
           m_fSensitivityRangeMin;

    // return in range
    result = max(m_fSensitivityRangeMin, result);
    result = min(m_fSensitivityRangeMax, result);

    result *= sensFactor;

    return result;
}


inline void CMouseSettingsDialog::restoreDefaults()
{
    m_nRotSensitivitySliderPos =
        (m_nSensitivitySliderRangeMax - m_nSensitivitySliderRangeMin) / 2;
    m_nTraSensitivitySliderPos =
        (m_nSensitivitySliderRangeMax - m_nSensitivitySliderRangeMin) / 2;
    m_nScaSensitivitySliderPos =
        (m_nSensitivitySliderRangeMax - m_nSensitivitySliderRangeMin) / 2;
}
